﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
using Microsoft.SharePoint;

namespace SKN
{
    /// <summary>
    /// Contains common method for CAML
    /// </summary>
    public static class CAML
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="listGuid"></param>
        /// <param name="itemID"></param>
        /// <param name="dictionary"></param>
        /// <returns></returns>
        
        private static string SaveMethodBuilder(Guid listGuid, int itemID, Dictionary<string, string> dictionary)
        {
            string methodFormat = string.Format("<Method ID=\"{0}\">", itemID) +
                                  string.Format("<SetList>{0}</SetList>", listGuid) +
                                  "<SetVar Name=\"Cmd\">Save</SetVar>" +
                                  string.Format("<SetVar Name=\"ID\">{0}</SetVar>", itemID);
            foreach (var kvp in dictionary)
            {
                methodFormat +=
                    string.Format("<SetVar Name=\"urn:schemas-microsoft-com:office:office#{0}\">{1}</SetVar>", kvp.Key,
                                  kvp.Value);
            }

            methodFormat += "</Method>";


            return methodFormat;
        }

        /// <summary>
        /// Use this method to Batch Update field(s) for list items returned based on CAML query condition
        /// </summary>
        /// <param name="web"></param>
        /// <param name="listName"></param>
        /// <param name="query"></param>
        /// <param name="dictionary"></param>
        public static void BatchUpdate(SPWeb web, string listName, string query, Dictionary<string, string> dictionary)
        {
            var methodBuilder = new StringBuilder();

            const string batchFormat =
                "<?xml version=\"1.0\" encoding=\"UTF-8\"?><ows:Batch OnError=\"Return\">{0}</ows:Batch>";

            // Get the list containing the items to update.
            SPList list = web.Lists[listName];

            //Query to get the unprocessed items.
            var spQuery = new SPQuery();
            spQuery.Query = query;
            spQuery.ViewAttributes = "Scope='Recursive'";
            SPListItemCollection itemsToBeProcessed = list.GetItems(spQuery);

            // Build the CAML update commands.
            foreach (SPListItem item in itemsToBeProcessed)
            {
                methodBuilder.Append(SaveMethodBuilder(list.ID, item.ID, dictionary));
            }

            // Put the pieces together.
            string batch = string.Format(batchFormat, methodBuilder);

            // Process the batch of commands.
            web.ProcessBatchData(batch);
        }


        /// <summary>
        /// Use this method to Batch Delete set of list item returned based CAML query condition
        /// </summary>
        /// <param name="web"></param>
        /// <param name="listName"></param>
        /// <param name="query"></param>
        public static void BatchDelete(SPWeb web, string listName, string query)
        {
            SPList list = web.Lists[listName];

            var sbDelete = new StringBuilder();

            sbDelete.Append("<?xml version=\"1.0\" encoding=\"UTF-8\"?><Batch>");

            sbDelete.Append("<Batch>");

            string command = "<Method><SetList Scope=\"Request\">" + list.ID + "</SetList>";
            command += "<SetVar Name=\"ID\">{0}</SetVar><SetVar Name=\"Cmd\">Delete</SetVar></Method>";


            // Query to get the unprocessed items.
            var spQuery = new SPQuery {Query = query, ViewAttributes = "Scope='Recursive'"};
            SPListItemCollection itemsToBeProcessed = list.GetItems(spQuery);

            // Build the CAML update commands.
            // Build the CAML update commands.
            foreach (SPListItem item in itemsToBeProcessed)
            {
                sbDelete.Append(string.Format(command, item.ID));
            }

            sbDelete.Append("</Batch>");

            web.ProcessBatchData(sbDelete.ToString());
            web.Update();
        }


        /// <summary>
        /// Use this method to quicky get a datatable with all the row items
        /// </summary>
        /// <param name="web"></param>
        /// <param name="listName"></param>
        /// <returns>Datatable with all the list items as rows</returns>
        public static DataTable GetListItems(SPWeb web, string listName)
        {
            SPList list = web.Lists[listName];

            //Query to fetch the assignment details for the passed Job number and Assignment Number where siteURL <> -
            DataTable table = list.Items.GetDataTable();
            return table;
        }

        /// <summary>
        /// Use this method to get list items using CAML query recursively.
        /// </summary>
        /// <param name="web"></param>
        /// <param name="listName"></param>
        /// <param name="query"></param>
        /// <returns></returns>
        /// <example>GetListItems(web,"Shared Documents",@"<Query><Where><Eq><FieldRef Name="ContentType" /><Value Type="Text">My Content Type</Value></Eq></Where></Query>");</example>
        public static SPListItemCollection GetListItems(SPWeb web, string listName, string query)
        {
            SPList list = web.Lists[listName];

            var spQuery = new SPQuery {Query = query, ViewAttributes = "Scope='Recursive'"};

            //Query to fetch the assignment details for the passed Job number and Assignment Number where siteURL <> -
            SPListItemCollection listItemCollection = list.GetItems(spQuery);
            return listItemCollection;
        }


        /// <summary>
        /// Use this method to get list items for a particular view using CAML 
        /// </summary>
        /// <param name="web"></param>
        /// <param name="listName"></param>
        /// <param name="viewName"></param>
        /// <returns></returns>
        public static SPListItemCollection GetListViewItems(SPWeb web, string listName, string viewName)
        {
            SPList list = web.Lists[listName];
            SPView view = list.Views[viewName];

            var query = new SPQuery(view) {ViewAttributes = "Scope=\"Recursive\""};
            return list.GetItems(query);
        }

        /// <summary>
        /// Use this method to get all the items from all the lists/document library for a particular list type
        /// </summary>
        /// <param name="web"></param>
        /// <param name="listType"></param>
        /// <param name="query"></param>
        /// <returns></returns>
        /// <example>CAML.GetListViewItems(web,107,"<Where><Eq><FieldRef Name=\"Status\"/><Value Type=\"Text\">Completed</Value></Eq></Where>");</example>
        public static DataTable GetListViewItems(SPWeb web, int listType, string query)
        {
            var spquery = new SPSiteDataQuery
                              {
                                  Lists = @"<Lists ServerTemplate=" + listType + @" />",
                                  Query = query
                              };

            return web.GetSiteData(spquery);
        }
    }
}